﻿#region File and License Information
/*
<File>
	<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
	<License see="//License.txt"/>
	<Owner Name="Daniel Vaughan" Email="danielvaughan@outcoder.com"/>
	<CreationDate>2008-12-21 11:19:31Z</CreationDate>
	<LastSubmissionDate>$Date: $</LastSubmissionDate>
	<Version>$Revision: $</Version>
</File>
*/
#endregion

using System;
using System.Diagnostics;
using System.Security;

using DanielVaughan.Logging.Installers;
using DanielVaughan.Logging.Resources;

namespace DanielVaughan.Logging
{
	/* TODO: [DV] Comment. */
	internal static class InternalLog
	{
		static LogLevel logLevelThreshold = LogLevel.All;
		static bool eventLogEnabled;

		static InternalLog()
		{
			try
			{
				CreateEventLog();
				eventLogEnabled = true;
			}
			catch (SecurityException ex)
			{
				Warn("EventLog source 'Clog' does not exist and could not be created. EventLog will not be written to.", ex); /* TODO: Make localizable resource. */
			}
		}

		internal static LogLevel LogLevel
		{
			get
			{
				return logLevelThreshold;
			}
			set
			{
				logLevelThreshold = value;
			}
		}
        
		static EventLog eventLog;
		static void CreateEventLog()
		{
			if (!EventLog.SourceExists(InternalLogEventLogInstaller.EventLogSource))
			{
				EventLog.CreateEventSource(InternalLogEventLogInstaller.EventLogSource, 
					InternalLogEventLogInstaller.EventLogLog);
			}
			eventLog = new EventLog { Source = InternalLogEventLogInstaller.EventLogSource };
		}

		static void WriteLogEntry(object message, LogLevel logLevel)
		{
			if (message == null || logLevel < logLevelThreshold)
			{
				return;
			}

			try
			{
				string prefix = string.Empty;
				switch (logLevel)
				{
					case LogLevel.Debug:
						prefix = StringResources.InternalLog_Prefix_Debug;
						break;
					case LogLevel.Info:
						prefix = StringResources.InternalLog_Prefix_Info;
						break;
					case LogLevel.Warn:
						prefix = StringResources.InternalLog_Prefix_Warn;
						break;
					case LogLevel.Error:
						prefix = StringResources.InternalLog_Prefix_Error;
						break;
					case LogLevel.Fatal:
						prefix = StringResources.InternalLog_Prefix_Fatal;
						break;
				}

				var exception = message as Exception;
				if (exception != null)
				{
					message = string.Format("{0} {1} {2} {3}", 
						prefix, message, exception.Message, exception.StackTrace);
				}
				else
				{
					message = prefix + message;
				}

				if (logLevel == LogLevel.Error || logLevel == LogLevel.Fatal)
				{
					Console.Error.WriteLine(message);
				}
				else
				{
					Console.Out.WriteLine(message);
				}
				
				Trace.WriteLine(message);

				if (eventLogEnabled)
				{
					EventLogEntryType eventLogEntryType;
					switch (logLevel)
					{
						case LogLevel.Error:
						case LogLevel.Fatal:
							eventLogEntryType = EventLogEntryType.Error;
							break;
						case LogLevel.Warn:
							eventLogEntryType = EventLogEntryType.Warning;
							break;
						default:
							eventLogEntryType = EventLogEntryType.Information;
							break;
					}
					                                      	
					try
					{
						eventLog.WriteEntry(message.ToString(), eventLogEntryType);
					}
					catch (Exception)
					{
						eventLogEnabled = false;
					}
				}
			}
			catch (Exception)
			{
				/* Ignore. There is nothing more we can do. */
			}
		}

		#region public write log overloads
		public static void Debug(string message)
		{
			WriteLogEntry(message, LogLevel.Debug);
		}

		public static void Debug(string message, Exception exception)
		{
			WriteLogEntry(message, LogLevel.Debug);
			WriteLogEntry(exception, LogLevel.Debug);
		}

		public static bool DebugEnabled
		{
			get
			{
				return LogLevel <= LogLevel.Debug;
			}
		}

		public static void Info(string message)
		{
			WriteLogEntry(message, LogLevel.Info);
		}

		public static void Info(string message, Exception exception)
		{
			WriteLogEntry(message, LogLevel.Info);
			WriteLogEntry(exception, LogLevel.Info);
		}

		public static bool InfoEnabled
		{
			get
			{
				return LogLevel <= LogLevel.Info;
			}
		}

		public static void Warn(string message)
		{
			WriteLogEntry(message, LogLevel.Warn);
		}

		public static void Warn(string message, Exception exception)
		{
			WriteLogEntry(message, LogLevel.Warn);
			WriteLogEntry(exception, LogLevel.Warn);
		}

		public static bool WarnEnabled
		{
			get
			{
				return LogLevel <= LogLevel.Warn;
			}
		}

		public static void Error(string message)
		{
			WriteLogEntry(message, LogLevel.Error);
		}

		public static void Error(string message, Exception exception)
		{
			WriteLogEntry(message, LogLevel.Error);
			WriteLogEntry(exception, LogLevel.Error);
		}

		public static bool ErrorEnabled
		{
			get
			{
				return LogLevel <= LogLevel.Error;
			}
		}

		public static void Fatal(string message)
		{
			WriteLogEntry(message, LogLevel.Fatal);
		}

		public static void Fatal(string message, Exception exception)
		{
			WriteLogEntry(message, LogLevel.Fatal);
			WriteLogEntry(exception, LogLevel.Fatal);
		}

		public static bool FatalEnabled
		{
			get
			{
				return LogLevel <= LogLevel.Fatal;
			}
		}
		#endregion
	}
}
